<!--
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
* Non open source, The copyright belongs to KylinSoft Co., Ltd. 
-->
<template>
  <div class="ky-table">
    <div class="header" v-if="ShowTableHeader">
      <div class="header-content">
        <div class="table-search">
          <div class="table-check" v-if="showSelect">
            <el-dropdown
              split-button
              ref="dropdownRef"
              @click="handleCheck"
              placement="bottom-start"
            >
              <span>
                <i class="icon iconfont" v-if="checked" style="font-size: 12px; color: #489eff"
                  >&#xe721;</i
                >
                <i class="icon iconfont" v-if="!checked" style="font-size: 12px">&#xe720;</i>
                <span v-if="checked && select_number !== 0">{{
                  $t('select_number').replace('%s', (select_number || 0).toString())
                }}</span>
              </span>
              <template #dropdown>
                <el-dropdown-menu @click="handleSelect">
                  <el-dropdown-item id="0">{{
                    $t('select_none').replace('%s', '0')
                  }}</el-dropdown-item>
                  <el-dropdown-item id="1">{{
                    $t('select_page').replace(
                      '%s',
                      ((objSearch.page_size || 0) * (objSearch.current_page || 1) > (total || 0)
                        ? (total || 0) -
                          ((objSearch.current_page || 1) - 1) * (objSearch.page_size || 0)
                        : objSearch.page_size || 0
                      ).toString(),
                    )
                  }}</el-dropdown-item>
                  <el-dropdown-item id="2">{{
                    $t('select_all').replace('%s', (total || 0).toString())
                  }}</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
          <template v-if="showSearchAndSelect">
            <slot name="search-select"></slot>
            <template v-if="showFuzzySearch">
              <div class="table-search-input">
                <el-tooltip placement="top" effect="dark" :content="content" :visible="displayTip">
                  <el-input
                    :placeholder="$t('Please input the content')"
                    :prefix-icon="ElIconSearch"
                    v-model="objSearch.search"
                    @blur="handleBlur"
                    @focus="handleFocus"
                    class="search-input"
                    :clearable="true"
                    @clear="handleFuzzySearch"
                    @keyup.enter="handleFuzzySearch(false, 1)"
                  >
                  </el-input>
                </el-tooltip>
              </div>
            </template>
            <!-- 高级搜索按钮 -->
            <template v-if="showAdvancedSearch">
              <el-button
                class="advanced-search kylin-item-button"
                @click="display = true"
                v-if="JSON.stringify(search_data) !== '{}'"
              >
                {{ '高级搜索' }}
              </el-button>
            </template>
          </template>
          <template v-if="showAdvancedSearch">
            <slot name="batch-search-button"></slot>
          </template>
        </div>
        <div class="table-action">
          <slot name="table-action"></slot>
        </div>
      </div>
    </div>
    <div class="content">
      <!-- 高级搜索弹窗 -->
      <el-dialog
        v-model="display"
        :title="'高级搜索'"
        :before-close="handleClose"
        :modal-append-to-body="modalAppendToBody"
        :append-to-body="appendToBody"
      >
        <advance-search
          v-if="display"
          :display="display"
          @search="handleAdvanceSearch"
          @reset="handleReset"
          @click="handleClose"
          :search_data="search_data"
          :modalTable="modalTable"
          :modalSearch="objSearch.search || ''"
        >
        </advance-search>
      </el-dialog>
      <el-table
        border
        cell-class-name="ky-cell-class"
        :header-cell-style="{ color: 'black', 'background-color': '#f6f8fd' }"
        :cell-style="{ color: 'black' }"
        v-loading="loading"
        ref="multipleTable"
        :data="tableData"
        tooltip-effect="dark"
        style="width: 100%"
        @select="handleSelectionChange"
        @sort-change="sortChange"
      >
        <el-table-column v-if="showSelect" type="selection" width="50"> </el-table-column>
        <slot name="table" class="tablebox"></slot>
        <template #empty v-if="customTableEmpty">
          <slot name="empty"></slot>
        </template>
      </el-table>
    </div>
    <div class="pagination">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="objSearch.current_page"
        :page-sizes="[20, 25, 50, 75, 100]"
        :page-size="objSearch.page_size"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  onBeforeUnmount,
  onActivated,
  onMounted,
  watch,
  nextTick,
  getCurrentInstance,
  useTemplateRef,
} from 'vue';
import AdvanceSearch from '@/components/AdvanceSearch/index.vue';
import { ElMessage } from 'element-plus';
import type { DropdownInstance, TableInstance } from 'element-plus';
import { useRoute, useRouter, type LocationQueryValue } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { Search as ElIconSearch, LocationFilled } from '@element-plus/icons-vue';

// ===================== 组件说明 =====================
// KyTable 是一个通用表格组件，集成了分页、选择、模糊搜索、高级搜索、批量操作等功能，
// 适用于后台管理系统的通用数据表格场景。
// ====================================================

// 路由、国际化、组件实例
const $route = useRoute();
const $router = useRouter();
const instance = getCurrentInstance()!;
const { t } = useI18n();
const _this = instance.proxy;

// ===================== props定义 =====================
// 支持多种表格场景的配置项
const props = defineProps({
  row_number: { type: Boolean, default: false }, // 是否显示行号
  showSelect: { type: Boolean, default: false }, // 是否显示多选
  showSearchAndSelect: { type: Boolean, default: false }, // 是否显示搜索和选择
  showFuzzySearch: { type: Boolean, default: false }, // 是否显示模糊搜索
  showAdvancedSearch: { type: Boolean, default: false }, // 是否显示高级搜索
  row_id_name: { type: String, default: 'id' }, // 行唯一标识字段
  rowClassName: { type: Function }, // 行样式回调
  search_data: { type: Object, default: () => ({}) }, // 搜索条件配置
  getData: { type: Function, required: true }, // 获取数据方法
  search_criteria: { type: Object, default: () => ({}) }, // 额外搜索条件
  content: { type: String, default: '' }, // 搜索提示内容
  watchs: { type: Object, default: () => ({}) }, // 监听属性
  modalAppendToBody: { type: Boolean, default: true }, // 弹窗是否追加到body
  appendToBody: { type: Boolean, default: false }, // 弹窗是否追加到body
  modalTable: { type: Boolean, default: false }, // 是否为弹窗表格
  keepSearch: { type: Boolean, default: true }, // 是否保持搜索条件
  ShowTableHeader: { type: Boolean, default: true }, // 是否显示表头
  customTableEmpty: { type: Boolean, default: false }, // 是否自定义空数据
});

// ===================== emits定义 =====================
// 事件类型定义
const emit = defineEmits<{
  record: [LocationQueryValue];
  reset: [];
  searchByExcelError: [];
  resetBatchSearch: [];
}>();

// ===================== 响应式数据 =====================
// 选中行相关
const checked = ref<boolean>(false); // 是否全选
const selectRow = ref<{
  ids: any[];
  rows: any[];
  rowNumbers: any[];
  excludeRows: any[];
  excludeIds: any[];
}>({
  ids: [],
  rows: [],
  rowNumbers: [],
  excludeRows: [],
  excludeIds: [],
});
const timer = ref<number | null>(null); // 定时器
const select_id = ref('0'); // 选择类型（0:无, 1:当前页, 2:全部）
const select_number = ref<number>(0); // 已选数量
const displayTip = ref<boolean>(false); // 搜索提示显示
const isInitialized = ref<boolean>(false); // 初始化标志，避免重复调用
interface ObjSearchType {
  current_page: number;
  page_size: number;
  search?: LocationQueryValue;
}
// 搜索、分页、排序相关
const objSearch = ref<ObjSearchType>({
  page_size: 20,
  current_page: 1,
  search: props.keepSearch ? ($route?.query.search as LocationQueryValue) || '' : '',
});
const total = ref(0); // 总条数
const loading = ref(true); // 加载状态
const tableData = ref<any[]>([]); // 表格数据
const display = ref(false); // 高级搜索弹窗显示
const search_criteria_copy = ref<Record<string, any>>({}); // 搜索条件副本
const sortBy = ref(''); // 排序字段
const sortOrder = ref(''); // 排序方式

// ===================== 模板引用 =====================
const dropdownRef = useTemplateRef<DropdownInstance | null>('dropdownRef'); // 下拉菜单ref
const multipleTable = useTemplateRef<TableInstance | null>('multipleTable'); // 表格ref

// ===================== 生命周期钩子 =====================
onBeforeUnmount(() => {
  // 组件卸载时清理定时器
  if (timer.value) {
    clearInterval(timer.value);
  }
});

onActivated(() => {
  // keep-alive激活时同步搜索条件
  objSearch.value.search = ($route?.query.search as LocationQueryValue) || '';
});

onMounted(() => {
  // 挂载时加载数据、监听props变化
  if ($route?.query.search_module) {
    loadData({ ...objSearch.value, current_page: 1, module: $route.query.search_module });
  } else {
    if (!props.keepSearch) {
      loadData({ ...objSearch.value });
    } else {
      loadData({ ...objSearch.value, ...$route?.query });
    }
  }
  for (const key in props.watchs) {
    if (Object.prototype.hasOwnProperty.call(props, key)) {
      const propKey = (props as { [key: string]: any })[key];
      watch(() => propKey, props.watchs[key]);
    }
  }
  isInitialized.value = true;
});

// ===================== 主要方法 =====================
// 数据加载方法

const loadData = (
  data: ObjSearchType & { module?: LocationQueryValue | LocationQueryValue[] } = {
    current_page: 1,
    page_size: 20,
  },
) => {
  loading.value = true;
  // 异步更新查询参数，避免tab和路由联动时出现问题
  setTimeout(() => {
    if (!props.modalTable) {
      $router.replace({
        query: {
          ...$route?.query,
          page: data.current_page,
          size: data.page_size,
          search: data.search || objSearch.value.search || '',
        },
      });
    }
  });
  data.search = data.search || objSearch.value.search;
  data.current_page = data.current_page || objSearch.value.current_page;
  data.page_size = data.page_size || objSearch.value.page_size;
  search_criteria_copy.value = { ...props.search_criteria };
  if (sortOrder.value) {
    search_criteria_copy.value.sortOrder = sortOrder.value;
    search_criteria_copy.value.sortBy = sortBy.value;
  }
  // 调用父组件传入的getData方法获取数据
  props.getData({ ...data, ...search_criteria_copy.value }).then((response: any) => {
    const res = response.data;
    if (res.code === 0 || res.code === '0' || res.code === 200) {
      objSearch.value.page_size = res.page_size;
      total.value = res.total;
      objSearch.value.current_page = res.current_page;
      loading.value = false;
      // Ensure tableData is always an array
      tableData.value = Array.isArray(res.data) ? res.data : [];
      // 处理主机不存在的告警
      if (tableData.value.length > 0 && tableData.value[0].warning) {
        try {
          const list = JSON.parse(tableData.value[0].warning);
          if (Array.isArray(list) && list.length > 0) {
            ElMessage.warning(`有 ${list.length}台主机不存在:${list.join(',')} `);
          }
        } catch (error) {
          console.error('解析警告信息失败:', error);
        }
      }
    } else if (res.code !== '401') {
      ElMessage.error(res.message);
      emit('searchByExcelError');
    }
  });
};

// 分页切换
const handleSizeChange = (size: number) => {
  objSearch.value.page_size = size;
  // 只有在组件初始化完成后才触发loadData，避免首次加载时的重复调用
  if (isInitialized.value) {
    loadData({ ...$route?.query, ...objSearch.value });
  }
};
const handleCurrentChange = (page: number) => {
  objSearch.value.current_page = page;
  // 只有在组件初始化完成后才触发loadData，避免首次加载时的重复调用
  if (isInitialized.value) {
    // loadData(objSearch.value);
  }
};

// 多选操作
const handleSelectionChange = (selection: any[], row: any) => {
  // 处理全选、当前页全选、单选等逻辑
  if (select_id.value === '2') {
    const id = props.row_number ? row.rowNumber : row[props.row_id_name];
    const index = selectRow.value.excludeIds.indexOf(id);
    if (index < 0) {
      selectRow.value.excludeIds.push(id);
      selectRow.value.excludeRows.push(row);
      select_number.value = select_number.value - 1;
    } else {
      selectRow.value.excludeIds.splice(index, 1);
      selectRow.value.excludeRows.splice(index, 1);
      select_number.value = select_number.value + 1;
    }
    checked.value = !!Number(select_number.value);
    return;
  }
  const id = props.row_number ? row.rowNumber : row[props.row_id_name];
  const indexProp = props.row_number ? 'rowNumbers' : 'ids';
  const index = selectRow.value[indexProp].indexOf(id);
  if (index < 0) {
    selectRow.value[indexProp].push(id);
    selectRow.value.rows.push(row);
  } else {
    selectRow.value[indexProp].splice(index, 1);
    selectRow.value.rows.splice(index, 1);
  }
  select_number.value = selectRow.value[indexProp].length;
  checked.value = !!Number(select_number.value);
};

// 搜索相关
const handleSearch = (keepcurPage?: string | boolean, firstPage?: number) => {
  if (
    keepcurPage !== 'clear' &&
    objSearch.value.search &&
    (objSearch.value.search.includes('[') || objSearch.value.search.includes(']'))
  ) {
    ElMessage.error(t('system.char_inputError'));
    return;
  }
  emit('record', objSearch.value.search || '');
  let current_page = keepcurPage ? objSearch.value.current_page : 1;
  current_page = firstPage === 1 ? 1 : current_page;
  checked.value = false;
  multipleTable.value?.clearSelection();
  selectRow.value = {
    ids: [],
    rows: [],
    rowNumbers: [],
    excludeRows: [],
    excludeIds: [],
  };
  select_number.value = 0;
  if ($route?.query.search_module) {
    loadData({
      ...objSearch.value,
      current_page: 1,
      module: $route.query.search_module,
    });
  } else {
    loadData({ ...objSearch.value, current_page });
  }
};

// 刷新表格
const refresh = () => {
  checked.value = false;
  multipleTable.value?.clearSelection();
  selectRow.value = {
    ids: [],
    rows: [],
    rowNumbers: [],
    excludeRows: [],
    excludeIds: [],
  };
  select_number.value = 0;
  loadData({ ...objSearch.value });
};

// 搜索输入框聚焦/失焦
const handleBlur = () => {
  displayTip.value = false;
};
const handleFocus = () => {
  if (props.content) {
    displayTip.value = true;
  }
};

// 全选/取消全选
const handleCheck = () => {
  checked.value = !checked.value;
  if (checked.value) {
    select_number.value = total.value;
    select_id.value = '2';
    selectRow.value.excludeRows = [];
    selectRow.value.excludeIds = [];
  } else {
    select_id.value = '0';
    select_number.value = 0;
  }
};

// 下拉选择操作
const handleSelect = (e: MouseEvent) => {
  const target = e.target as HTMLElement;
  select_id.value = target.id;
  if (select_id.value === '0') {
    checked.value = false;
  } else if (select_id.value === '1') {
    checked.value = true;
    tableData.value.forEach((row) => {
      multipleTable.value?.toggleRowSelection(row, true);
      const id = props.row_number ? row.rowNumber : row[props.row_id_name];
      const indexProp = props.row_number ? 'rowNumbers' : 'ids';
      const index = selectRow.value[indexProp].indexOf(id);
      if (index < 0) {
        selectRow.value[indexProp].push(id);
        selectRow.value.rows.push(row);
      }
    });
    select_number.value = props.row_number
      ? selectRow.value.rowNumbers.length
      : selectRow.value.ids.length;
  } else {
    checked.value = true;
    select_number.value = total.value;
    selectRow.value.excludeIds = [];
    selectRow.value.excludeRows = [];
  }
};

// 重置搜索
const handleReset = () => {
  emit('reset');
};

// 关闭高级搜索弹窗
const handleClose = () => {
  display.value = false;
};
// 重置搜索状态的方法
const resetSearch = () => {
  objSearch.value = {
    page_size: 20,
    current_page: 1,
    search: '',
  };
  search_criteria_copy.value = { ...props.search_criteria };
  sortBy.value = '';
  sortOrder.value = '';
  display.value = false; // 关闭高级搜索弹窗
  select_id.value = '0';
  select_number.value = 0;
  checked.value = false;
  loadData({ ...objSearch.value });
};
// 模糊搜索
const handleFuzzySearch = (keepcurPage?: string | boolean, firstPage?: number) => {
  emit('resetBatchSearch');
  nextTick(() => {
    handleSearch(keepcurPage, firstPage);
  });
};

// 搜索回调
const handleAdvanceSearch = (search: string) => {
  display.value = false;
  objSearch.value.search = search;
  emit('record', search);
  emit('resetBatchSearch');
  nextTick(() => {
    handleSearch();
  });
};

// 选中行同步
const handleSelectRow = () => {
  if (checked.value) {
    if (select_id.value === '2') {
      tableData.value.forEach((row) => {
        const id = props.row_number ? row.rowNumber : row[props.row_id_name];
        if (!selectRow.value.excludeIds.includes(id)) {
          multipleTable.value?.toggleRowSelection(row, true);
        }
        const indexProp = props.row_number ? 'rowNumbers' : 'ids';
        const index = selectRow.value[indexProp].indexOf(id);
        if (index < 0) {
          selectRow.value[indexProp].push(id);
          selectRow.value.rows.push(row);
        }
      });
    } else {
      const indexProp = props.row_number ? 'rowNumbers' : 'ids';
      tableData.value.forEach((row) => {
        const id = props.row_number ? row.rowNumber : row[props.row_id_name];
        if (selectRow.value[indexProp].indexOf(id) > -1) {
          multipleTable.value?.toggleRowSelection(row, true);
        }
      });
    }
  } else {
    multipleTable.value?.clearSelection();
    selectRow.value = {
      ids: [],
      rows: [],
      rowNumbers: [],
      excludeRows: [],
      excludeIds: [],
    };
    select_id.value = '0';
    select_number.value = 0;
  }
};

// 排序变更
const sortChange = ({ order, prop }: { order: string | null; prop: string }) => {
  let orderNew = '';
  if (order === 'ascending') {
    orderNew = 'asc';
  } else if (order === 'descending') {
    orderNew = 'desc';
  }
  sortBy.value = prop;
  sortOrder.value = orderNew;
  loadData({ ...$route?.query, ...objSearch.value });
};

// 计算属性
const checkOrSelectId = () => ({ checked: checked.value, select_id: select_id.value });

// 监听表格数据和选中状态，自动同步选择
watch(tableData, () => {
  nextTick(() => {
    handleSelectRow();
  });
});

watch(checkOrSelectId, () => {
  nextTick(() => {
    handleSelectRow();
  });
});

// 监听 props.search_criteria 的变化
watch(
  () => props.search_criteria,
  (newVal, oldVal) => {
    // 避免初始化时重复调用
    if (isInitialized.value && oldVal && JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
      search_criteria_copy.value = { ...newVal };
      // loadData({ ...objSearch.value });
    }
  },
  { deep: true }, // 移除 immediate: true，避免组件挂载时重复调用
);

// ===================== 向外暴露方法 =====================
defineExpose({
  selectRow,
  objSearch,
  select_id,
  select_number,
  tableData,
  handleSearch,
  resetSearch,
  refresh,
});
</script>

<style lang="scss" scoped>
.ky-table {
  padding: 24px;
  background: #fff;
  border: 1px solid #dcdfe6;
  .header {
    width: auto;
    background-color: #fff;
    margin-bottom: 24px;

    .header-content {
      display: flex;
      justify-content: space-between;

      .table-search {
        flex: 1;
        display: flex;

        .table-search-input {
          margin-right: 10px;
        }

        .table-check {
          margin-right: 10px;
        }

        .search-input {
          width: 200px;
        }

        .advanced-search {
          margin-left: 0px;
        }

        .batch-search {
          margin-left: 10px;
        }
      }
    }
  }

  .el-table {
    border-color: #ebeef5;
    .line-color {
      background-color: #f2f7ff;
    }
  }

  .pagination {
    margin-top: 16px;
    .el-pagination {
      text-align: right;
      padding-top: 5px;
      padding-bottom: 5px;
      border-top: 0px;
      justify-content: flex-end;
      .el-pagination__sizes,
      .el-pagination__total {
        float: left;
      }
    }
  }
}

.el-message {
  .el-message__content {
    max-width: 800px !important;
    word-break: break-all;
  }
}
</style>
